package com.yzkj.framework.core.util.jwt;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import com.yzkj.framework.beans.exception.YzkjException;

import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;

/**
 * Jwt AES 加解密工具类
 *
 */
final class JwtAesUtils {

    /**
     * 秘钥大小
     */
    private static final int KEY_SIZE = 128;

    /**
     * 密钥算法名称
     */
    private static final String ALGORITHM_NAME = "AES";

    /**
     * Jwt AES 加密
     *
     * @param data 待加密内容
     * @param key  秘钥
     * @return AES 加密后的数据
     */
    static String encryptToStr(String data, String key) {
        return parseByte2HexStr(encrypt(data, key));
    }

    /**
     * Jwt AES 解密
     *
     * @param encryptData 待解密字节数组
     * @param key         秘钥
     * @return 加密后的数据
     */
    static String decryptToStr(String encryptData, String key) {
        return new String(decrypt(parseHexStr2Byte(encryptData), key), StandardCharsets.UTF_8);
    }

    /**
     * AES 加密数据
     *
     * @param data 待加密数据
     * @param key  秘钥
     * @return 解密结果
     */
    private static byte[] encrypt(String data, String key) {
        return crypto(Cipher.ENCRYPT_MODE, data.getBytes(StandardCharsets.UTF_8), key);
    }

    /**
     * AES 解密数据
     *
     * @param data 待解密字节数组
     * @param key  秘钥
     * @return 解密结果
     */
    private static byte[] decrypt(byte[] data, String key) {
        return crypto(Cipher.DECRYPT_MODE, data, key);
    }

    /**
     * 加解密数据
     */
    private static byte[] crypto(int mode, byte[] content, String key) {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM_NAME);
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(key.getBytes());
            keyGenerator.init(KEY_SIZE, random);
            SecretKey secretKey = keyGenerator.generateKey();
            SecretKeySpec keySpec = new SecretKeySpec(secretKey.getEncoded(), ALGORITHM_NAME);
            Cipher cipher = Cipher.getInstance(ALGORITHM_NAME);
            cipher.init(mode, keySpec);
            return cipher.doFinal(content);
        } catch (Exception e) {
            throw YzkjException.of("Jwt AES 加解密失败", e);
        }
    }

    /**
     * 将字节数组转为 16 进制字符串
     *
     * @param bytes 字节数组
     * @return 16 进制字符串
     */
    private static String parseByte2HexStr(byte[] bytes) {
        StringBuilder sBuilder = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(b & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sBuilder.append(hex.toUpperCase());
        }
        return sBuilder.toString();
    }

    /**
     * 将 16 进制字符串转换为字节数组
     *
     * @param hexStr 16 进制字符串
     * @return 字节数组
     */
    private static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1) {
            throw YzkjException.of("16 进制字符串转字节数组错误");
        }
        int length = hexStr.length() / 2;
        byte[] result = new byte[length];
        for (int i = 0; i < length; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }

    private JwtAesUtils() {
    }

}
